/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package creature;

import processing.core.PApplet;
import processing.core.PVector;
import world.StateRepository;

/**
 *
 * @author user
 */
public class PredatorCreature {

    PApplet parent;
    PVector loc;
    PVector vel;
    PVector acc;
    float maxspeed;
    float maxsteer;
    float wandertheta;
    float sightrange;
    private StateRepository state;

    public PredatorCreature(PApplet parent, StateRepository state, PVector loc) {
        this.parent = parent;
        this.state = state;
        this.loc = loc;
        this.vel = new PVector(0, 0);
        this.acc = new PVector(0, 0);

        this.maxspeed = 5;
        this.maxsteer = 2;

        this.wandertheta = parent.random(-1, 1);
        this.sightrange = 50;
    }

    /**
     * Returns a steering vector with full steering power.
     * @param target
     * @return
     */
    private PVector steer(PVector target) {
        PVector steer;
        PVector desired = PVector.sub(target, loc);
        float distance = desired.mag();

        if (distance > 0) {

            desired.normalize();
            desired.mult(this.maxspeed);

            steer = PVector.sub(desired, vel);
            steer.limit(maxsteer);  // Limit to maximum steering force

        } else {
            return new PVector(0, 0);
        }
        return steer;
    }

    /**
     * Method for seek only behaviour
     * @param target
     */
    private void seek(PVector target) {
        // steer towards target
        acc.add(steer(target));
    }

    public void update() {
        // WANDER
        wander();
        // SEEK IF CLOSE
        PVector target = AntLibrary.getClosestAnt(loc, sightrange, state.getAnts());
        if(target != null) {
            seek(target);
        }
        // UPDATE
        vel.add(acc);
        vel.limit(maxspeed);
        loc.add(vel);
    }

    public void display() {
        float heading = vel.heading2D();
        parent.pushMatrix();
        parent.translate(loc.x, loc.y);
        parent.rotate(heading);
        parent.stroke(192, 64, 0);
        parent.rect(0, 0, 12, 6);
        parent.popMatrix();
    }

    /**
     * Reynold's wandering.
     */
    public void wander() {
        float wanderR = 16.0f;         // Radius for our "wander circle"
        float wanderD = 60.0f;         // Distance for our "wander circle"
        float change = 0.25f;
        wandertheta += parent.random(-change, change);     // Randomly change wander theta

        // Now we have to calculate the new location to steer towards on the wander circle
        PVector circleloc = new PVector(vel.x, vel.y);  // Start with velocity
        circleloc.normalize();            // Normalize to get heading
        circleloc.mult(wanderD);          // Multiply by distance
        circleloc.add(loc);               // Make it relative to boid's location

        PVector circleOffSet = new PVector(wanderR * PApplet.cos(wandertheta), wanderR * PApplet.sin(wandertheta));
        PVector target = PVector.add(circleloc, circleOffSet);
        acc.add(steer(target));  // Steer towards it


    }
}